package com.zerro.litez.runtime;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.boot.json.GsonJsonParser;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

public abstract class EntityFormatter<T> {

    protected static Map<String, EntityFormatter<?>> formatterMap = new HashMap<>();

    protected Map<String, List<T>> queriedPrimaryKeysEntities = new HashMap<>();

    protected abstract String getValueOrDefaultOf(T entity, int index);

    protected abstract String getNameOf(int index);

    @SafeVarargs
    public final String values(T... entities) {
        List<String> values = new ArrayList<>();
        for (T entity : entities) {
            values.add(valuesOf(entity));
        }
        String arrStr = values.toString();
        return arrStr.substring(1, arrStr.length() - 1);

    }

    /**
     * 获得所有非自增的字段值，
     *
     * @param entity 实体对象
     * @return 字符串： v1,v2,v3
     */
    protected abstract String valuesOf(T entity);

    protected abstract <E> E resultSetToEntity(ResultSet resultSet, LitEzSupporter supporter);

    protected <E> E selectEntity(LitEzSupporter supporter, String name, String pk, String value, boolean strType, int index) throws SQLException {
        if (strType) {
            value = "'" + escape(value) + "'";
        }
        String[] splitName = name.split("\\.");
        String tableName = splitName[splitName.length - 1];
        EntityFormatter<E> formatter = (EntityFormatter<E>) formatterMap.get(name);
        List<E> primaryKeysEntities = formatter.getQueriedPrimaryKeysEntities(pk);
        if (primaryKeysEntities != null) {
            for (E entity : primaryKeysEntities) {
                if (formatter.getValueOrDefaultOf(entity, index).equals(value)) {
                    return entity;
                }
            }
        }

        ResultSet resultSet = supporter.getStmt("select * from " + tableName + " where " + pk + " = " + value, false)
                .executeQuery();

        resultSet.last();
        if (resultSet.getRow() == 0) {
            return null;
        }

        resultSet.first();
        return formatter.resultSetToEntity(resultSet, supporter);
    }

    protected void clearQueried() {
        for (String s : queriedPrimaryKeysEntities.keySet()) {
            queriedPrimaryKeysEntities.put(s, new ArrayList<>());
        }
    }

    @SafeVarargs
    public final String getPrimaryKeyValues(T... entities) {
        StringBuilder str = new StringBuilder();
        if (entities.length > 1) {
            for (int i = 0; i < entities.length; i++) {
                T entity = entities[i];
                str.append("(")
                        .append(getPrimaryKeyValue(entity))
                        .append(")");
                if (i < entities.length - 1) {
                    str.append(" or ");
                }
            }
        } else {
            str.append(getPrimaryKeyValue(entities[0]));
        }
        return str.toString();
    }

    protected abstract String getPrimaryKeyValue(T entity);

    protected abstract int getColumnCount();

    protected abstract Integer getAutoIncIndex();

    public abstract void setGeneratedKeysValue(T entity, ResultSet resultSet) throws SQLException;

    protected void throwNotnull(String name, String col) {
        throw new RuntimeException("Entity<" + name + ">的 field<" + col + ">不能为空值");
    }

    public static EntityFormatter<?> getFormatter(String name) {
        return formatterMap.get(name);
    }

    protected String[] parseStrArray(String strArr) {
        List<?> list = parseList(strArr);
        if (list == null) {
            return null;
        }
        return parseList(strArr).toArray(new String[0]);
    }

    /** 将Json数组字符串转换为字符串列表
     *
     * @param strArr Json数组字符串
     * @return 字符串列表
     */
    protected List<?> parseList(String strArr) {
        if (strArr == null || strArr.isEmpty()) {
            return null;
        }
        GsonJsonParser parser = new GsonJsonParser();
        return parser.parseList(strArr);
    }

    Gson gson = new Gson();

    protected <L> String simpleListToString(Collection<L> list) {
        if (list == null || list.isEmpty()) {
            return "";
        }
        return gson.toJson(list);
    }
    protected <L> String listToString(Collection<L> list, String name, int index) {
        if (list == null || list.isEmpty()) {
            return "";
        }
        arrayToString(list.toArray(), name, index);
        return gson.toJson(list);
    }


    protected <A> String arrayToString(A[] arr) {
        if (arr == null || arr.length == 0) {
            return "";
        }
        return gson.toJson(arr);
    }

    protected <A extends Enum<?>> String arrayToString(A[] arr) {

        if (arr == null || arr.length == 0) {
            return "";
        }
        String[] values = new String[arr.length];
        for (int i = 0; i < arr.length; i++) {
            values[i] = arr[i].name();
        }
        return gson.toJson(values);
    }

    protected <A> String arrayToString(A[] arr, String name, int index) {
        if (arr == null || arr.length == 0) {
            return "";
        }
        EntityFormatter<A> formatter = (EntityFormatter<A>) getFormatter(name);
        String[] values = new String[arr.length];
        for (int i = 0; i < arr.length; i++) {
            String value = formatter.getValueOrDefaultOf(arr[i], index);
            if (value.startsWith("'") &&value.endsWith("'")) {
                value = value.substring(1, value.length() - 1);
            } else if (value.contains("'")) {
                value = escape(value);
            }
            values[i] = value;
        }
        return gson.toJson(values);
    }

    protected <E> List<E> getQueriedPrimaryKeysEntities(String pk) {
        return (List<E>) queriedPrimaryKeysEntities.get(pk);
    }

    /**
     * 将字符串中的 ' 转义为 \'
     */
    protected String escape(String str) {
        if (str == null) {
            return "";
        }
        return str.replace("'", "\\'");
    }
}

